package com.mars.ms.sychronized;

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * author by: mars
 * Date: 2022/2/28 23:43
 * Description: 使用 ReentrantLock 2
 */
public class ReentLockInterruptDemo2 {

    final static int max = 10;
    LinkedList<Integer> queue = new LinkedList<>();
    ReentrantLock lock = new ReentrantLock();
    // 满栈条件
    Condition fullLock = lock.newCondition();
    // 空栈条件
    Condition emptyLock = lock.newCondition();

    int readData() throws InterruptedException{
        Thread.sleep((long)Math.random() *1000);
        return (int)Math.floor(Math.random());
    }

    // 生产者
    public void readDb() throws InterruptedException {
        lock.lock();
        // 队列满了，停止生产，等待消费
        if (queue.size() == max) {
            System.out.println("停止生产....");
            fullLock.await();
            return;
        }
        int num = readData();
        // 队列元素==1，唤醒消费者
        if (queue.size() == 1) {
            emptyLock.signal();
        }
        queue.add(num);
        lock.unlock();
    }

    // 消费者
    public void calculate () throws InterruptedException {
        lock.lock();
        // 队列空了，停止消费
        if (queue.size() == 0 ) {
            System.out.println("停止消费....");
            emptyLock.await();
            return;
        }

        Integer data = queue.remove();
        // 唤醒生产者
        System.out.println("queue-size:" +queue.size());
        if (queue.size() == max -1) {
            fullLock.signal();
        }
        data = data * 100;
        lock.unlock();
    }

    public static void main(String[] args) {
        ReentLockInterruptDemo2 demo2 = new ReentLockInterruptDemo2();
        for (int i = 0; i < 100; i++) {
            new Thread(()->{
               while (true) {
                   try {
                       demo2.readDb();
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
            }).start();

        }

        new Thread(()->{
            while (true) {
                try {
                    demo2.calculate();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();

    }
}
